package com.example.st.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.example.st.service.AmapService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.HashMap;
import java.util.Map;

@Service
public class AmapServiceImpl implements AmapService {
    @Value("${amap.key}")
    public String apiKey;

    private final RestTemplate restTemplate = new RestTemplate();

    private final String WALKING_URL = "https://restapi.amap.com/v3/direction/walking";
    private final String TRANSIT_URL = "https://restapi.amap.com/v3/direction/transit/integrated";
    private final String DRIVING_URL = "https://restapi.amap.com/v3/direction/driving";
    private final String BICYCLING_URL = "https://restapi.amap.com/v4/direction/bicycling";

    private final String GEOCODE_URL = "https://restapi.amap.com/v3/geocode/regeo";

    // 将 routeInfo 转换为 JSON 字符串
    //String jsonRouteInfo = JSON.toJSONString(routeInfo);
    @Override
    public Map<String, Object> getRouteInfo(String origin, String destination) {
        Map<String, Object> result = new HashMap<>();
        result.put("walking", getWalkingInfo(origin, destination));
        result.put("transit", getTransitInfo(origin, destination));
        result.put("driving", getDrivingInfo(origin, destination));
        result.put("bicycling", getBicyclingInfo(origin, destination));
        return result;
    }

    private String getCityInfo(String location) {
        String url = UriComponentsBuilder.fromHttpUrl(GEOCODE_URL)
                .queryParam("location", location)
                .queryParam("key", apiKey)
                .toUriString();
        String response = restTemplate.getForObject(url, String.class);
        return parseCityFromGeocodeResponse(response);
    }

    private String parseCityFromGeocodeResponse(String response) {
        if (response != null && !response.isEmpty()) {
            try {
                JSONObject jsonObject = JSON.parseObject(response, Feature.OrderedField);
                JSONObject regeocode = jsonObject.getJSONObject("regeocode");
                JSONObject addressComponent = regeocode.getJSONObject("addressComponent");
                String cityCode = addressComponent.getString("citycode");

                return cityCode; // 返回解析到的城市名称
            } catch (Exception e) {
                e.printStackTrace(); // 在实际应用中，应进行适当的错误处理
            }
        }

        return ""; // 如果解析失败或响应为空，则返回空字符串
    }


    private Map<String, Object> getWalkingInfo(String origin, String destination) {
        String url = UriComponentsBuilder.fromHttpUrl(WALKING_URL)
                .queryParam("origin", origin)
                .queryParam("destination", destination)
                .queryParam("key", apiKey)
                .toUriString();
        String response = restTemplate.getForObject(url, String.class);
        return parseWalkingResponse(response);
    }

    private Map<String, Object> getTransitInfo(String origin, String destination) {

        // 调用地理编码API获取起点和终点城市信息
        String originCity = getCityInfo(origin);
        String destinationCity = getCityInfo(destination);

        String url = UriComponentsBuilder.fromHttpUrl(TRANSIT_URL)
                .queryParam("origin", origin)
                .queryParam("destination", destination)
                .queryParam("city", originCity)
                .queryParam("cityd", destinationCity)
                .queryParam("output", "json")
                .queryParam("key", apiKey)
                .toUriString();
        String response = restTemplate.getForObject(url, String.class);
        return parseTransitResponse(response);
    }

    private Map<String, Object> getDrivingInfo(String origin, String destination) {
        String url = UriComponentsBuilder.fromHttpUrl(DRIVING_URL)
                .queryParam("origin", origin)
                .queryParam("destination", destination)
                .queryParam("key", apiKey)
                .toUriString();
        String response = restTemplate.getForObject(url, String.class);
        return parseDrivingResponse(response);
    }

    private Map<String, Object> getBicyclingInfo(String origin, String destination) {
        String url = UriComponentsBuilder.fromHttpUrl(BICYCLING_URL)
                .queryParam("origin", origin)
                .queryParam("destination", destination)
                .queryParam("key", apiKey)
                .toUriString();
        String response = restTemplate.getForObject(url, String.class);
        return parseBicyclingResponse(response);
    }

    private Map<String, Object> parseWalkingResponse(String response) {
        Map<String, Object> info = new HashMap<>();
        try {
            // Parse JSON response using Fastjson
            JSONObject jsonObject = JSON.parseObject(response, Feature.OrderedField);

            /*Check if status is "1" (indicating success)
            String status = jsonObject.getString("status");
            if (!"1".equals(status)) {
                // Handle error or non-successful response
                info.put("error", "Error in API response");
                return info;
            }*/

            // Navigate to the paths array and get the first path (assuming only one path is returned)
            JSONObject route = jsonObject.getJSONObject("route");
            JSONObject firstPath = route.getJSONArray("paths").getJSONObject(0);

            // Extract duration
            Integer durationSeconds = firstPath.getInteger("duration");
            int hours = durationSeconds / 3600;
            int minutes = (durationSeconds % 3600) / 60;
            int seconds = durationSeconds % 60;

            // Construct formatted duration string
            String formattedDuration = String.format("%02d:%02d:%02d", hours, minutes, seconds);
            // Put duration into info map
            info.put("duration", formattedDuration);

            // Since cost for walking is usually free, you can optionally add this information
            double cost = 0;
            info.put("cost", cost);

        } catch (Exception e) {
            // Handle any exception that occurs during JSON parsing
            info.put("error", "Exception during parsing: " + e.getMessage());
        }

        return info;
    }

    private Map<String, Object> parseTransitResponse(String response) {
        Map<String, Object> info = new HashMap<>();
        try {
            // Parse JSON response using Fastjson
            JSONObject jsonObject = JSON.parseObject(response, Feature.OrderedField);

            /*Check if status is "1" (indicating success)
            String status = jsonObject.getString("status");
            if (!"1".equals(status)) {
                // Handle error or non-successful response
                info.put("error", "Error in API response");
                return info;
            }*/

            // Navigate to the paths array and get the first path (assuming only one path is returned)
            JSONObject route = jsonObject.getJSONObject("route");
            JSONObject firstTransit = route.getJSONArray("transits").getJSONObject(0);

            // Extract duration
            Integer durationSeconds = firstTransit.getInteger("duration");
            int hours = durationSeconds / 3600;
            int minutes = (durationSeconds % 3600) / 60;
            int seconds = durationSeconds % 60;

            // Construct formatted duration string
            String formattedDuration = String.format("%02d:%02d:%02d", hours, minutes, seconds);
            // Put duration into info map
            info.put("duration", formattedDuration);

            String costStr = firstTransit.getString("cost");
            double cost = Double.parseDouble(costStr);
            info.put("cost", cost);

        } catch (Exception e) {
            // Handle any exception that occurs during JSON parsing
            info.put("error", "Exception during parsing: " + e.getMessage());
        }

        return info;
    }

    private Map<String, Object> parseDrivingResponse(String response) {
        Map<String, Object> info = new HashMap<>();
        try {
            // Parse JSON response using Fastjson
            JSONObject jsonObject = JSON.parseObject(response, Feature.OrderedField);

            /*Check if status is "1" (indicating success)
            String status = jsonObject.getString("status");
            if (!"1".equals(status)) {
                // Handle error or non-successful response
                info.put("error", "Error in API response");
                return info;
            }*/

            // Navigate to the paths array and get the first path (assuming only one path is returned)
            JSONObject route = jsonObject.getJSONObject("route");
            JSONObject firstPath = route.getJSONArray("paths").getJSONObject(0);

            // Extract duration
            // Extract duration
            Integer durationSeconds = firstPath.getInteger("duration");
            int hours = durationSeconds / 3600;
            int minutes = (durationSeconds % 3600) / 60;
            int seconds = durationSeconds % 60;

            // Construct formatted duration string
            String formattedDuration = String.format("%02d:%02d:%02d", hours, minutes, seconds);
            // Put duration into info map
            info.put("duration", formattedDuration);
            Integer distance = firstPath.getInteger("distance");

            //　3公里以内收费
            //　　13元
            //　　基本单价
            //　　2.3元/公里
            double cost = 0;
            if(distance<=3000){
                cost = 13;
            } else {
                //上取整
                cost = 13 + Math.ceil((distance-3000.0)/1000.0) * 2.3;
                // 将费用保留一位小数
                cost = Math.round(cost * 10.0) / 10.0;
            }
            //根据路线距离和时间计算费用
            info.put("cost", cost);

        } catch (Exception e) {
            // Handle any exception that occurs during JSON parsing
            info.put("error", "Exception during parsing: " + e.getMessage());
        }

        return info;
    }

    private Map<String, Object> parseBicyclingResponse(String response) {
        Map<String, Object> info = new HashMap<>();
        try {
            // Parse JSON response using Fastjson
            JSONObject jsonObject = JSON.parseObject(response, Feature.OrderedField);

            /*Check if status is "1" (indicating success)
            String status = jsonObject.getString("status");
            if (!"1".equals(status)) {
                // Handle error or non-successful response
                info.put("error", "Error in API response");
                return info;
            }*/

            // Navigate to the paths array and get the first path (assuming only one path is returned)
            JSONObject data = jsonObject.getJSONObject("data");
            JSONObject firstPath = data.getJSONArray("paths").getJSONObject(0);

            // Extract duration
            Integer durationSeconds = firstPath.getInteger("duration");
            int hours = durationSeconds / 3600;
            int minutes = (durationSeconds % 3600) / 60;
            int seconds = durationSeconds % 60;

            // Construct formatted duration string
            String formattedDuration = String.format("%02d:%02d:%02d", hours, minutes, seconds);
            // Put duration into info map
            info.put("duration", formattedDuration);

            double durationInMinutes = durationSeconds / 60.0;

            // Calculate cost based on duration
            double cost = 0;
            if (durationInMinutes <= 30) {
                cost = 1.5;
            } else {
                // Calculate additional 30-minute blocks
                //上取整
                double additionalBlocks = Math.ceil((durationInMinutes - 30) / 30);
                cost =  1.5 + additionalBlocks * 1.5;
            }
            //根据路线距离和时间计算费用
            info.put("cost", cost);

        } catch (Exception e) {
            // Handle any exception that occurs during JSON parsing
            info.put("error", "Exception during parsing: " + e.getMessage());
        }

        return info;
    }
}
